## -*- coding: utf-8 -*-
import json
import os
import random
import re
import urllib
import urllib2
import urlparse
import uuid
from django.conf.urls import url
from django.contrib.auth import authenticate, logout, login
from django.contrib.auth.models import User
from django.db.models import Q, get_model
import poster
from poster.streaminghttp import register_openers
from tastypie import fields
from tastypie.authentication import ApiKeyAuthentication, MultiAuthentication, BasicAuthentication, \
    SessionAuthentication
from tastypie.authorization import DjangoAuthorization
from tastypie.constants import ALL_WITH_RELATIONS
from tastypie.http import HttpUnauthorized, HttpAccepted, HttpApplicationError
from tastypie.models import ApiKey
from tastypie.resources import ModelResource, ALL, Resource
from tastypie.utils.urls import trailing_slash
from django.utils.translation import ugettext_lazy as _
from app.helper import VectorExt
from app.models import Vector
from eVB1 import settings


class UserResource(ModelResource):
    class Meta:
        queryset = User.objects.all()
        fields = ['first_name', 'last_name', 'email', 'username', 'id']
        filtering = {
            'id': ALL
        }
        list_allowed_methods = ['get', 'post']
        resource_name = 'user'
        always_return_data = True

    def override_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/login%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('login'), name="api_login"),
            url(r'^(?P<resource_name>%s)/logout%s$' % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('logout'), name='api_logout')
        ]

    def login(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        data = self.deserialize(request, request.raw_post_data,
                                format=request.META.get('CONTENT_TYPE', 'application/json'))
        print data
        username = data.get('username', '')
        password = data.get('password', '')

        user = authenticate(username=username, password=password)
        if user:
            login(request, user)
            return self.create_response(request, {'success': True})
        else:
            return self.create_response(request, {'success': False, 'reason': unicode(_('Username or password error!')), },
                                        HttpUnauthorized)

    def logout(self, request, **kwargs):
        self.method_check(request, allowed=['get'])
        if request.user and request.user.is_authenticated():
            logout(request)
            return self.create_response(request, {'success': True})
        else:
            return self.create_response(request, {'success': False}, HttpUnauthorized)


class VectorResource(ModelResource):
    class Meta:
        queryset = Vector.objects.all()
        resource_name = 'vector'
        list_allowed_methods = ['get', 'post', 'put', 'delete', 'patch']
        detail_allowed_methods = ['get', 'post', 'put', 'delete', 'patch']
        authorization = DjangoAuthorization()
        authentication = MultiAuthentication(BasicAuthentication(), ApiKeyAuthentication(), SessionAuthentication())
        always_return_data = True
        # serializer = UrlEncodeSerializer() # IMPORTANT
        max_limit = 0
        filtering = {  # ALL_WITH_RELATIONS ALL
                       'quote': ALL_WITH_RELATIONS,
                       'sales_order': ALL_WITH_RELATIONS,
                       'invoice': ALL_WITH_RELATIONS,
                       'vector_name': ALL,
                       'gb_text': ALL,
                       'svg_text': ALL,
                       'ext_text': ALL,
                       'img_data': ALL,
                       'uuid': ALL,
        }

    def dehydrate(self, bundle):
        # Include the request IP in the bundle.
        request_obj = bundle.request.REQUEST
        if not 'limit' in request_obj:
            try:
                bundle.data['ext'] = json.loads(bundle.data['ext_info'])
            except Exception as e:
                bundle.data['ext'] = {}
                print e

            ext = VectorExt(bundle.obj)
            bundle.data['discount'] = ext.get_discount()
            bundle.data['slug'] = 'v1{}'.format(str(bundle.obj.id).zfill(7))

            # 相关关键信息 todo: 先不改这段
            bundle.data['info'] = {
                'is_quote': random.choice([True, False]),
                'is_order': random.choice([True, False]),
                'is_invoice': random.choice([True, False]),
                'shipping': [
                    {'tm': '2013-01-01 11:22:33', 'content': 'China ...'},
                    {'tm': '2013-01-02 11:22:33', 'content': 'USA ...'},
                ],
                'progress': random.randint(30, 100)
            }

        return bundle

    def obj_update(self, bundle, request=None, **kwargs):
        #print type(bundle.obj)
        bundle = super(VectorResource, self).obj_update(bundle, **kwargs)

        for field_name in self.fields:
            field = self.fields[field_name]
            if type(field) is fields.ToOneField and field.null and bundle.data[field_name] is None:
                setattr(bundle.obj, field_name, None)

        bundle.obj.save()

        return bundle

    def build_filters(self, filters=None):
        if filters is None:
            filters = {}
        orm_filters = super(VectorResource, self).build_filters(filters)

        if 'query' in filters:
            query = filters['query']
            qset = (
                Q(vector_name__icontains=query) |
                Q(uuid=query) |
                Q(ext_info__icontains=query) |
                Q(comment__icontains=query)
            )
            orm_filters.update({'custom': qset})

        return orm_filters

    def apply_filters(self, request, applicable_filters):
        if 'custom' in applicable_filters:
            custom = applicable_filters.pop('custom')
        else:
            custom = None

        semi_filtered = super(VectorResource, self).apply_filters(request, applicable_filters)

        return semi_filtered.filter(custom) if custom else semi_filtered

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/test%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('test'), name="api_test"),
        ]

    def test(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        data = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json'))

        if True:
            return self.create_response(request, {'success': True}, HttpAccepted)
        else:
            return self.create_response(request, {'success': False, 'reason': 'incorrect', }, HttpApplicationError)

    def get_more_info(self, vector_obj):
        print 'vector get_more_info'
        print dir(vector_obj)
        obj_dict = {'id': vector_obj.id}
        return obj_dict




################## No ORM Resource ######################################



class OtherResource(Resource):
    # result = fields.CharField(attribute='result')

    class Meta:
        resource_name = 'other'
        allowed_methods = ['get', 'post']

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/uuid%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('uuid'), name="api_uuid"),
            url(r"^(?P<resource_name>%s)/test%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('test'), name="api_test"),
            url(r"^(?P<resource_name>%s)/summary%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('summary'), name="api_summary"),
            url(r"^(?P<resource_name>%s)/file_upload%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('file_upload'), name="api_file_upload"),
            url(r"^(?P<resource_name>%s)/post_file/(?P<path>.*)%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('post_file'), name="api_post_file"),
            url(r"^(?P<resource_name>%s)/get_more_info%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('get_more_info'), name="api_get_more_info"),
        ]

    def get_more_info(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        data = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json'))
        print data
        class_name = data.get('currentModel', None)
        obj_id = data.get('objId', None)
        if class_name and obj_id:
            model_class = get_model('app', class_name)
            model_obj = model_class.objects.get(id=obj_id)
            # if class_name == 'invoice':
            #     info_dict = InvoiceResource().get_more_info(model_obj)
            # if class_name == 'salesorder':
            #     info_dict = SalesOrderResource().get_more_info(model_obj)
            # if class_name == 'quote':
            #     info_dict = QuoteResource().get_more_info(model_obj)
            if class_name == 'vector':
                info_dict = VectorResource().get_more_info(model_obj)
                # setattr(modelObj, fieldName, newData)
                # modelObj.__setattr__(fieldName, newData)
                # modelObj.save()
        return self.create_response(request, {'status': 1, 'obj': info_dict})

    def file_upload(self, request, **kwargs):
        # print 'http://vb31.vb3.com/ajax-upload-unsafe/attachment/'
        # req = request.REQUEST
        # fileObj = request.FILES.get('file', None)
        # print 'req=', req
        # print 'fileObj=', fileObj
        # print self.post_method(url='http://vb31.vb3.com/ajax-upload-unsafe/attachment/', data=fileObj)

        return self.create_response(request, {'status': 1, 'obj': 'dddddddd'})

    def summary(self, request, **kwargs):
        self.method_check(request, allowed=['get'])
        obj = {
            'chartData': {
                'newContacts': [
                    {'name': 'USA', 'y': random.randint(100, 200)},
                    {'name': 'China', 'y': random.randint(100, 200)},
                    {'name': 'Europe', 'y': random.randint(100, 200)},
                    {'name': 'Others', 'y': random.randint(100, 200)}
                ],
                'newQuotes': [
                    {'name': 'Ordered', 'y': random.randint(100, 200)},
                    {'name': 'Other', 'y': random.randint(20, 100)}
                ],
                'newRequirements': [
                    {'name': 'Replied', 'y': random.randint(100, 200)},
                    {'name': 'Other', 'y': random.randint(20, 100)}
                ],
                'newVectors': [
                    {'name': 'Standard', 'y': random.randint(100, 200)},
                    {'name': 'Non-standard', 'y': random.randint(10, 50)}
                ]
            }
        }
        return self.create_response(request, {'status': 1, 'obj': obj})

    def generate_slug(self, request, **kwargs):
        self.method_check(request, allowed=['get'])

        return self.create_response(request, {'status': 1, 'uuid': uuid.uuid4()})

    def test(self, request, **kwargs):
        return self.create_response(request, {'status': 1, 'uuid': uuid.uuid4()})

    def get_method(self, params={}, username=settings.API_USERNAME, api_key=settings.API_KEY,
                   url=settings.VB_DOMAIN + '/api/v1/msg/evb_group_list/'):
        paramStr = ''
        if params:
            for key in params:
                if params.has_key(key):
                    paramStr += '&' + str(key) + '=' + str(params.get(key))
        url = url + '?username=' + username + '&api_key=' + api_key + paramStr
        response = urllib2.urlopen(url)
        con = response.read()
        data = json.loads(con)
        return data

    def post_method(self, url, data):
        req = urllib2.Request(url)
        data = urllib.urlencode(data)
        #enable cookie
        # opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
        # response = opener.open(req, data)
        response = urllib2.urlopen(req, data)
        return response.read()

    def post_json_method(self, url, jsonObj):
        req = urllib2.Request(url)
        # data = urllib.urlencode(data)
        #enable cookie
        # opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
        # response = opener.open(req, data)
        # response = urllib2.urlopen(req, data)
        req.add_header('Content-Type', 'application/json')
        # req.add_header('Host', 'www.i-md.com')
        response = urllib2.urlopen(req, json.dumps(jsonObj))
        return response.read()

    def post_file(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        # data = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json'))
        path = kwargs.get('path')
        print 'post_file', request.REQUEST
        target_url = request.REQUEST.get('target_url', None)
        if not target_url:
            target_url = settings.VB_DOMAIN
        url = os.path.join(target_url, path)
        if not re.match('.*/$', str(url)):
            url += '/'
        fileObj = request.FILES.get('file', None)
        file_dir = os.path.join(settings.MEDIA_ROOT, fileObj.name)
        with open(file_dir, 'wb') as fw:
            fw.write(fileObj.read())
        # 在 urllib2 上注册 http 流处理句柄
        register_openers()
        # headers 包含必须的 Content-Type 和 Content-Length
        # datagen 是一个生成器对象，返回编码过后的参数，这里如果有多个参数的话依次添加即可
        # datagen, headers = multipart_encode({"file": fileObj.read()})  open("/home/robert/Desktop/Region1.csv", "rb")
        datagen, headers = poster.encode.multipart_encode({'attachment': open(file_dir, "rb")})
        # 创建请求对象
        # request1 = urllib2.Request(url, datagen, headers)
        request1 = urllib2.Request(url, datagen, headers)
        # 实际执行请求并取得返回
        postResult = json.loads(urllib2.urlopen(request1).read())
        # print 'post_file postResult', postResult
        if postResult.get('success') and postResult.get('object', None):
            object = postResult.get('object', None)
            oldPath = object.get('path', '')
            object['path'] = urlparse.urljoin(str(target_url), str(oldPath))
        os.remove(file_dir)
        return self.create_response(request, postResult)

    def api_key_authenticated(self, username, api_key):
        keys = ApiKey.objects.filter(user__username=username, key=api_key)
        return keys